package com.smartcruise.data.cruiseData;

import android.text.TextUtils;

import com.smartcruise.util.ListUtils;
import com.smartcruise.util.TimeUtils;

import io.realm.RealmList;
import io.realm.RealmObject;
import io.realm.annotations.PrimaryKey;

/**
 * Created by FengChaoQun
 * on 2018/2/27 0027
 * 一个巡航任务的所有信息
 * 注意:
 * 1.在一个任务执行之前 如果有网络 先从服务器更新该任务
 * 2.复制需要执行的任务 在复制的任务里面填充数据
 * <p>
 * 几中任务概念：
 * 1.原任务：表示从服务器下发的任务 这是一个模板 前端根据cronExpression可以生成无穷多的任务
 * 原任务和其余任务的主要区别是 id和patrollingTaskId相同 或 isCopyData为false且isFromNet为false
 * 2.本地生成的任务：从原任务生成而来，与其他的任务的区别是 isCopyData为true
 * 3.网络上的任务：从服务器拉取的已经上传的任务，与其他任务的区别是 isFromNet为true
 */

public class CruiseData extends RealmObject {

    @PrimaryKey
    private String id;      //表示一个任务的id 任务由初始的巡航任务生产出来
    private String patrollingTaskId;//巡航任务的id 这个id唯一标识一个初始巡航任务 注意 一个初始的巡航任务可以产生很多待执行的任务
    private String auditorId;//审核人员id
    private String costTime;//预计耗时(小时)
    private String cronExpression;//cron表达式
    private String downWay;//下发方式
    private String inspectorId;//巡护人员id
    private String mapId;//巡护地图id
    private String name;//任务名称
    private String nodeTask;//所有节点任务的字符串,用来临时接受前端传过来的数据
    private String routeId;//巡护路线id
    private String statusInApp;//APP端此任务的状态
    private String threshold;//偏离阀值
    private String type;//类型
    private RealmList<NodeTaskListBean> nodeTaskList;//节点任务列表
    private AuditorBean auditor;//审核人员
    private InspectorBean inspector;//巡护人员
    private PatrollingMapEntityBean patrollingMapEntity;//巡护地图
    private PatrollingRouteEntityBean patrollingRouteEntity;//巡护路线
    private long shouldRunDate;//应该执行的日期
    private long actualRunDate;//实际执行的日期
    private long actualStopDate;//结束时间
    private String pauseStartDate;//任务执行的时间段 格式 a-b#c-d
    private RealmList<MapElementEntityListBean> mapElementEntityList;//地图上的标记物
    private String auditResult;//审核结果
    private int auditStatus;//审核状态 0表示未审核 1表示已审核
    private long auditTime;//审核时间
    private String evaluation;//评语
    private long storageTime;//入库时间

    /**
     * ***********************************本地便捷字段**********************************
     */
    private long lastStartTime;//最近一次开始时间
    private int uploadStatus;//0未上传 1部分上传 2全部上传
    /**
     * description:表示是否是复制出来的本地任务
     * 在复制一个任务的时候设置为true
     */
    private boolean isCopyData;//标记是否是复制出来的任务
    /**
     * description:服务器端id 在任务数据上传到服务器后更新该字段
     */
    private String serverId;//服务器端该任务的id
    /**
     * description:当一个本地复制出来的任务到了将要执行的时间 提醒用户执行 然后将该字段设置为true
     */
    private boolean notice;//记录是否提醒过用户
    /**
     * description:标记数据是否改动过
     * 主要是针对被驳回的任务 检查是否需要上传
     */
    private boolean dataChanged;
    /**
     * description:从服务器上拉取已经上传的任务 存储到本地的时候 设置该字段为true
     */
    private boolean isFromNet;//标记数据是否从服务器下载过来的

    /**
     * ********************************************便捷方法*******************************************
     */

    /**
     * description:复制出一份任务的时候 调用此方法 设置本地任务临时id
     * id的格式是patrollingTaskId#shouldRunDate
     */

    public void buildTempleLocalId() {
        setId(getPatrollingTaskId() + "#" + getShouldRunDate());
    }

    /**
     * description:上传任务之前对id做一些处理 如果是本地任务第一次上传 则不传id
     * 如果不是本地任务 则不用操作
     * 该方法只有不是数据库中的实体才能调用 因为数据库中不允许修改主键
     */

    public void backUpId() {
        if (isFromNet()) {
            return;
        }
        setId(serverId);
    }

    /**
     * description:暂停任务的时候 添加执行时间段到数据库
     */

    public void addPauseTime() {
        String executeTime = lastStartTime + "-" + TimeUtils.currentTime() + "#";
        if (TextUtils.isEmpty(pauseStartDate)) {
            setPauseStartDate(executeTime);
        } else {
            setPauseStartDate(pauseStartDate + executeTime);
        }
    }

    /**
     * description:更新当前任务数据的上传状态 一般在上传单个节点任务的时候调用
     */

    public void buildUploadType() {
        if (ListUtils.isHaveContent(getNodeTaskList())) {
            int count0 = 0;
            int count1 = 0;
            int count2 = 0;
            for (NodeTaskListBean nodeTaskListBean : getNodeTaskList()) {
                if (nodeTaskListBean.getUploadStatus() == 2) {
                    count2++;
                } else if (nodeTaskListBean.getUploadStatus() == 1) {
                    count1++;
                } else {
                    count0++;
                }
            }

            if (count1 != 0) {
                setUploadStatus(1);
            } else if (count0 == getNodeTaskList().size()) {
                setUploadStatus(0);
            } else if (count2 == getNodeTaskList().size()) {
                setUploadStatus(2);
            } else {
                setUploadStatus(1);
            }
        }
    }

    /**
     * description:检查任务需要的数据是否齐全
     */

    public boolean checkContent() {
        if (!ListUtils.isHaveContent(getNodeTaskList())) {
            return true;
        }
        for (NodeTaskListBean nodeTaskListBean : getNodeTaskList()) {
            if (!nodeTaskListBean.checkContent(this)) {
                return false;
            }
        }
        return true;
    }

    /**
     * description:检查是否含有大的本地数据
     */

    public boolean isHaveBigLocalFile() {
        if (ListUtils.isHaveContent(getNodeTaskList())) {
            for (NodeTaskListBean nodeTaskListBean : getNodeTaskList()) {
                if (nodeTaskListBean.isHaveBigLocalFile()) {
                    return true;
                }
            }
        }
        return false;
    }

    /**
     * description:检查任务是否可以开始
     * 1.任务预定时间前一个小时即可开始任务
     */

    public boolean isCanStart() {
        return shouldRunDate - TimeUtils.currentTime() <= 60 * 60 * 1000;
    }

    /**
     * description:检查任务是否审核通过
     */

    public boolean isAuditSuccess() {
        return auditStatus == CruiseContract.AUDITED && CruiseContract.AUDIT_SUCCESS.equals(auditResult);
    }

    /**
     * description:清空本地资源
     */

    public void clearOriginalFiles() {
        if (ListUtils.isHaveContent(getNodeTaskList())) {
            for (NodeTaskListBean nodeTaskListBean : getNodeTaskList()) {
                nodeTaskListBean.clearOriginalFiles();
            }
        }
    }

    /**
     * description:获取实际消耗的时间
     * 1.如果任务尚未开始 则不用计算耗时
     * 2.如果任务已结束 则计算开始到结束之间的耗时
     * 3.如果任务尚未结束 则计算开始到当前之间的时间
     */

    public String getRealCostTime() {
        if (CruiseContract.isStarted(this) && getActualRunDate() > 0) {
            if (getActualStopDate() > 0) {
                return TimeUtils.getUsedTime(getActualStopDate() - getActualRunDate());
            } else {
                return TimeUtils.getUsedTime(TimeUtils.currentTime() - getActualRunDate());
            }
        }
        return null;
    }

    public AuditorBean getAuditor() {
        return auditor;
    }

    public void setAuditor(AuditorBean auditor) {
        this.auditor = auditor;
    }

    public String getAuditorId() {
        return auditorId;
    }

    public void setAuditorId(String auditorId) {
        this.auditorId = auditorId;
    }

    public String getCostTime() {
        return costTime;
    }

    public void setCostTime(String costTime) {
        this.costTime = costTime;
    }

    public String getCronExpression() {
        return cronExpression;
    }

    public void setCronExpression(String cronExpression) {
        this.cronExpression = cronExpression;
    }

    public String getDownWay() {
        return downWay;
    }

    public void setDownWay(String downWay) {
        this.downWay = downWay;
    }

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public InspectorBean getInspector() {
        return inspector;
    }

    public void setInspector(InspectorBean inspector) {
        this.inspector = inspector;
    }

    public String getInspectorId() {
        return inspectorId;
    }

    public void setInspectorId(String inspectorId) {
        this.inspectorId = inspectorId;
    }

    public String getMapId() {
        return mapId;
    }

    public void setMapId(String mapId) {
        this.mapId = mapId;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getNodeTask() {
        return nodeTask;
    }

    public void setNodeTask(String nodeTask) {
        this.nodeTask = nodeTask;
    }

    public PatrollingMapEntityBean getPatrollingMapEntity() {
        return patrollingMapEntity;
    }

    public void setPatrollingMapEntity(PatrollingMapEntityBean patrollingMapEntity) {
        this.patrollingMapEntity = patrollingMapEntity;
    }

    public PatrollingRouteEntityBean getPatrollingRouteEntity() {
        return patrollingRouteEntity;
    }

    public void setPatrollingRouteEntity(PatrollingRouteEntityBean patrollingRouteEntity) {
        this.patrollingRouteEntity = patrollingRouteEntity;
    }

    public String getRouteId() {
        return routeId;
    }

    public void setRouteId(String routeId) {
        this.routeId = routeId;
    }

    public String getStatusInApp() {
        return statusInApp;
    }

    public void setStatusInApp(String statusInApp) {
        this.statusInApp = statusInApp;
    }

    public String getThreshold() {
        return threshold;
    }

    public void setThreshold(String threshold) {
        this.threshold = threshold;
    }

    public String getType() {
        return type;
    }

    public void setType(String type) {
        this.type = type;
    }

    public RealmList<NodeTaskListBean> getNodeTaskList() {
        return nodeTaskList;
    }

    public void setNodeTaskList(RealmList<NodeTaskListBean> nodeTaskList) {
        this.nodeTaskList = nodeTaskList;
    }

    public long getShouldRunDate() {
        return shouldRunDate;
    }

    public void setShouldRunDate(long shouldRunDate) {
        this.shouldRunDate = shouldRunDate;
    }

    public long getActualRunDate() {
        return actualRunDate;
    }

    public void setActualRunDate(long actualRunDate) {
        this.actualRunDate = actualRunDate;
    }

    public long getActualStopDate() {
        return actualStopDate;
    }

    public void setActualStopDate(long actualStopDate) {
        this.actualStopDate = actualStopDate;
    }

    public String getPauseStartDate() {
        return pauseStartDate;
    }

    public void setPauseStartDate(String pauseStartDate) {
        this.pauseStartDate = pauseStartDate;
    }

    public long getLastStartTime() {
        return lastStartTime;
    }

    public void setLastStartTime(long lastStartTime) {
        this.lastStartTime = lastStartTime;
    }

    public int getUploadStatus() {
        return uploadStatus;
    }

    public void setUploadStatus(int uploadStatus) {
        this.uploadStatus = uploadStatus;
    }

    public String getPatrollingTaskId() {
        return patrollingTaskId;
    }

    public void setPatrollingTaskId(String patrollingTaskId) {
        this.patrollingTaskId = patrollingTaskId;
    }

    public boolean isCopyData() {
        return isCopyData;
    }

    public void setCopyData(boolean copyData) {
        isCopyData = copyData;
    }

    public String getServerId() {
        return serverId;
    }

    public void setServerId(String serverId) {
        this.serverId = serverId;
    }

    public RealmList<MapElementEntityListBean> getMapElementEntityList() {
        return mapElementEntityList;
    }

    public void setMapElementEntityList(RealmList<MapElementEntityListBean> mapElementEntityList) {
        this.mapElementEntityList = mapElementEntityList;
    }

    public boolean isNotice() {
        return notice;
    }

    public void setNotice(boolean notice) {
        this.notice = notice;
    }

    public String getAuditResult() {
        return auditResult;
    }

    public void setAuditResult(String auditResult) {
        this.auditResult = auditResult;
    }

    public int getAuditStatus() {
        return auditStatus;
    }

    public void setAuditStatus(int auditStatus) {
        this.auditStatus = auditStatus;
    }

    public long getAuditTime() {
        return auditTime;
    }

    public void setAuditTime(long auditTime) {
        this.auditTime = auditTime;
    }

    public String getEvaluation() {
        return evaluation;
    }

    public void setEvaluation(String evaluation) {
        this.evaluation = evaluation;
    }

    public long getStorageTime() {
        return storageTime;
    }

    public void setStorageTime(long storageTime) {
        this.storageTime = storageTime;
    }

    public boolean isDataChanged() {
        return dataChanged;
    }

    public void setDataChanged(boolean dataChanged) {
        this.dataChanged = dataChanged;
    }

    public boolean isFromNet() {
        return isFromNet;
    }

    public void setFromNet(boolean fromNet) {
        isFromNet = fromNet;
    }
}
